﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Configuration;
using System.ServiceProcess;
using PDB.DotNetSDK;
using System.Data;
using System.Xml;
using System.Threading;
using OpcUaHelper;
using Opc.Ua;

namespace OPCCollect
{
    class Program
    {
        static void Main(string[] args)
        {
            List<TagInfo> tagList = GetTagInfo();

            CollectTask collectTask = new CollectTask(tagList);
            collectTask.OpcServer = ConfigurationManager.AppSettings["OPCServer"].Trim();
            collectTask.DBTable = ConfigurationManager.AppSettings["PDBTable"].Trim();
            collectTask.PdbServer = ConfigurationManager.AppSettings["PDBConnStr"].Trim();

            collectTask.RunTask();

            while(true)
            {
                Console.ReadLine();
            }
        }


        //初始化OPC点表配置信息
        private static List<TagInfo> GetTagInfo()
        {
            XmlDocument xml = new XmlDocument();
            xml.Load("./opctag.xml");
            XmlNodeList tagList = xml.SelectNodes("/Tags/Tag");
            Dictionary<string, TagInfo> tagDic = new Dictionary<string, TagInfo>();
            foreach(XmlNode node in tagList)
            {
                string dbTag = node.Attributes["DBTag"].Value.Trim();
                string opcTag = node.Attributes["OPCTag"].Value.Trim();
                string opcType = node.Attributes["OpcType"].Value.Trim().ToLower();
                if (string.IsNullOrEmpty(dbTag) || string.IsNullOrEmpty(opcTag) || string.IsNullOrEmpty(opcType))
                {
                    Console.WriteLine("错误的配置项【" + node.OuterXml + "】");
                    continue;
                }

                if (tagDic.ContainsKey(dbTag.ToUpper()))
                {
                    Console.WriteLine("重复的数据库标签【" + dbTag + "】");
                    continue;
                }

                if (opcType.Equals("real") || opcType.Equals("int"))
                {
                    double coeff = 1;
                    XmlNode coeffNode = node.Attributes["Coeff"];
                    if (coeffNode != null)
                    {
                        coeff = Convert.ToDouble(coeffNode.Value);
                    }

                    TagInfo tagInfo = new TagInfo() { 
                        DevName = dbTag,
                        OpcName = opcTag,
                        OpcType = opcType,
                        Coefficient = coeff
                    };
                    tagDic.Add(dbTag.ToUpper(), tagInfo);
                }
                else if (opcType.Equals("bool"))
                {
                    TagInfo tagInfo = new TagInfo()
                    {
                        DevName = dbTag,
                        OpcName = opcTag,
                        OpcType = "bool"
                    };
                    tagDic.Add(dbTag.ToUpper(), tagInfo);
                }
            }

            Dictionary<string, long> dbNameToIdDic = QueryDBNameToIdDic();
            foreach(KeyValuePair<string, TagInfo> tagPair in tagDic)
            {
                if (dbNameToIdDic.ContainsKey(tagPair.Key))
                {
                    tagPair.Value.DevId = dbNameToIdDic[tagPair.Key];
                }
                else
                {
                    Console.WriteLine("标签【" + tagPair.Key + "】在数据库中不存在");
                }
            }

            return tagDic.Where(p=>p.Value.DevId > 0).Select(p => p.Value).ToList();
        }

        private static Dictionary<string, long> QueryDBNameToIdDic()
        {
            Dictionary<string, long> nameToIdDic = new Dictionary<string, long>();
            string pdbConn = ConfigurationManager.AppSettings["PDBConnStr"];
            string tabName = ConfigurationManager.AppSettings["PDBTable"];
            using (PDBConnection conn = new PDBConnection(pdbConn))
            {
                conn.Open();
                PDBCommand cmd = conn.CreateCommand();
                //能够处理1万个点以下的情况
                const int batch = 1000;
                int start = 0;
                do
                {
                    string sql = string.Format("SELECT devid,devname FROM sys_dev WHERE tabname = '{0}' LIMIT {1},{2}", tabName, start, batch);
                    DataTable dt = cmd.ExecuteQuery(sql);
                    foreach(DataRow dr in dt.Rows)
                    {
                        long devId = Convert.ToInt64(dr["devid"]);
                        string devName = dr["devname"].ToString().ToUpper();
                        if (string.IsNullOrEmpty(devName))
                        {
                            Console.WriteLine("数据库中存在名称为空的设备");
                        }

                        if (!nameToIdDic.ContainsKey(devName))
                        {
                            nameToIdDic.Add(devName, devId);
                        }
                        else
                        {
                            Console.WriteLine("数据库中存在重复的标签名【" + devName + "】");
                        }
                    }
                    start += dt.Rows.Count;
                } while (start > 0 && start % batch == 0);

                return nameToIdDic;
            }
        }
    }
}
